<?php

namespace app\anding\logic;

use app\anding\model\AndingUser;
use app\third\model\ThirdBind;
use Overtrue\Socialite\Providers\WeChatProvider;
use Overtrue\Socialite\SocialiteManager as Socialite;
use suframe\thinkAdmin\traits\SingleInstance;

class WxLogic
{
    use SingleInstance;

    protected $sdk;

    protected $type = 'app';
    protected $bindType = 'weixin';

    /**
     * @return WeChatProvider
     * @throws \Exception
     */
    public function getSdk()
    {
        if ($this->sdk) {
            return $this->sdk;
        }
        switch ($this->type) {
            case 'app':
                $thinkConfig = thinkConfigs('weixin_login.*');
                $config = [
                    'app_id' => $thinkConfig['weixin_login_appid'],
                    'secret' => $thinkConfig['weixin_login_secret'],
                ];
                //https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx856bb5884a355aae&secret=ee9aef55fffdc802a64ea1adc840c73e&code=081MwIRr03Unhj1dveSr0XLKRr0MwIRu&grant_type=authorization_code
                /** @var WeChatProvider $socialite */
                $socialite = (new Socialite([
                    'wechat' => [
                        'client_id' => $config['app_id'],
                        'client_secret' => $config['secret'],
                        'redirect' => '',
                    ],
                ]))->driver('wechat');
                break;
            case 'pc':
                $thinkConfig = thinkConfigs('weixin_pc_login.*');
                $config = [
                    'app_id' => $thinkConfig['weixin_pc_login_appid'],
                    'secret' => $thinkConfig['weixin_pc_login_secret'],
                ];
                /** @var WeChatProvider $socialite */
                $socialite = (new Socialite([
                    'wechat' => [
                        'client_id' => $config['app_id'],
                        'client_secret' => $config['secret'],
                        'redirect' => $thinkConfig['weixin_pc_login_backurl'],
                    ],
                ]))->driver('wechat');
                $this->bindType = 'weixin_pc';
                break;
        }
        $scopes = ['snsapi_userinfo'];
        if (!empty($scopes)) {
            $socialite->scopes($scopes);
        }
        return $socialite;
    }

    public function auth($code)
    {
        try {
            trace($code);
            $token = $this->getSdk()->getAccessToken($code);
            $rs = $this->getSdk()->user($token)->toArray();
            return $rs;
        } catch (\Exception $e) {
            trace($e->getMessage());
            return [];
        }
    }

    public function bindWx($code, $user = null)
    {
        $info = $this->auth($code);
        if (!$info || !isset($info['id'])) {
            return false;
        }

        $openId = $info['id'];
        $bind = ThirdBind::where('type', $this->bindType)
            ->where('account', $openId)->find();
        if (!$bind) {
            $bind = new ThirdBind();
            $rs = $bind->save([
                'uid' => $user ? $user['id'] : 0,
                'type' => $this->bindType,
                'account' => $openId,
                'context' => $info,
                'unionid' => $info['original']['unionid'],
            ]);
            if (!$rs) {
                return false;
            }
        }
        if (!$bind['uid'] && $info['original']['unionid']) {
            //通过 unionid 查找已经绑定的用户
            $hasBind = ThirdBind::where('unionid', $info['original']['unionid'])
                ->where('uid', '>', 0)
                ->find();
            if ($hasBind) {
                $bind['uid'] = $hasBind['uid'];
                $bind->save();
            }
        }
        //更新用户信息
        if ($bind['uid']) {
            if (!$user) {
                $user = AndingUser::find($bind['uid']);
            }
            $this->updateUserInfo($bind, $user, $info);
        }
        return $bind;
    }

    public function getUrl()
    {
        $oauth = $this->getSdk();
        $backurl = thinkConfigs('weixin_pc_login.weixin_pc_login_backurl');
        return $oauth->scopes(['snsapi_userinfo', 'snsapi_login'])->redirect($backurl);
    }

    public function bindUserByOpenid($openid, $user)
    {
        $bind = ThirdBind::where('type', $this->bindType)
            ->where('account', $openid)->find();
        if (!$bind) {
            return false;
        }
        if (!$bind->uid) {
            $bind->uid = $user['id'];
            $bind->save();
        }
        $info = $bind['context'];
        $this->updateUserInfo($bind, $user, $info);
    }

    protected function updateUserInfo($bind, $user, $info)
    {
        $hasChange = false;
        if (!$user['name'] || (strpos('用户', $user['name']) === 0)) {
            $user->name = $info['nickname'];
            $hasChange = true;
        }
        trace('头像更新');
        trace($user['avatar']);
        trace($info['avatar']);
        if ($info['avatar'] && (!$user['avatar'] || ($user['avatar'] == 'http://oss.adsafety.com.cn/avatar.png'))) {
            try {
                $avatar = WxAvatarLogic::getInstance()->saveAvatar($info['avatar']);
                $avatar = $avatar ?: $info['avatar'];
                $user->avatar = $avatar;
                $hasChange = true;
            } catch (\Exception $e) {
            }
        }
        if ($hasChange) {
            $user->save();
        }
    }

    /**
     * @return string
     */
    public function getType(): string
    {
        return $this->type;
    }

    /**
     * @param string $type
     */
    public function setType(string $type): void
    {
        $this->type = $type;
    }

}